{***************************************************************
    SpyGestion  Copyright (C) 2008 Christophe KOALI <nature2gas@gmail.com>
    
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    
****************************************************************}
unit modPlanete;

interface

uses Classes, SysUtils, modCore,
     modBaseType,
     ESBDates,
     sFonctionsChaines,


     modXML,
     
     modActionManager,
     modClassRessources,
     modClassElements;

 
type



    // Le programme doit offrir la possibilité de voir où l'on en est sans
    // pour autant se connecter
    TPlaneteInfo = class(TObject)
    private
        // Pour estimer quand on peut effectuer la prochaine action
        // Ces données sont sauvegardées dans le fichier texte
        FActionDateFinBatiment: int64;

        // Le chantier spatial est en fait INUTILE car il a sa propore
        // liste d'attente gérer sur le serveur, donc on n'est pas obligé
        // d'attendre la fin d'une construction pour passer à l'autre
        // MAIS on va utiliser ce champ pour savoir quand le chantier sera
        // libre (et pourra donc construirement immédiatement ce qu'on lui
        // met dans sa liste)
        FActionDateFinChantierSpatial: int64;

        // Pour éviter le flood d'essai à chaque seconde du timer, on fixe
        // une date à atteindre avant le réessayage
        FActionDateCanReTry: int64;


        // Determine la date de dernier calcul des ressources
        FActionDateDernierCalculRessource: int64;


        // Lors de la mise à jour de la liste de planète, il se peut
        // que l'une d'entre elle (voir plusieurs) furent détruite
        // dans ce cas là, ce flag reste à TRUE
        // On ne fait pas un clear de la liste des planètes lors de la mise
        // à jour pour éviter de perdre la liste d'action
        FHaveNOTBeenUpdated: boolean;



        {$IFDEF DEBUG}
            FDebugProc: TsfcProcStatus;
        {$ENDIF}


        // Dernière mise à jour de la page Apercu
        FDateLastApercuUpdate: int64;

        // Listes des ressources
        FListRessources: TListRessources;

        // Listes des ressouces qui contiennent les nouvelles
        // activité à définir
        //FListRessourcesToSet: TListRessources;

        // Liste des éléments
        FListElements  : TListElements;

        // Liste des actions
        FActionsList: TCollectionElementActionItem;


        
        {$IFDEF SIMULATOR}

        {$ENDIF}

        {$IFDEF DEBUG}
             procedure DoDebug(const Msg: string);
             procedure SetDebugProc(Element: TsfcProcStatus);
        {$ENDIF}



        procedure LoadLigne(Ligne: string);

        function GetShouldUpdateAppercu: boolean;
        procedure SetShouldUpdateAppercu(Valeur: boolean);
        function GetRessourceProd: TOGRessourceAll;
        function GetLocationStr: string;

        function GetEstimatedRessources: TOGRessourceAll;

    public
        (***********************************************************************
                         Informations basiques
        ***********************************************************************)

        // Position
        FLocation             : TPlanetLocation;
        FIsPlanetMere         : boolean;

        // Nom
        FNom : string;

        // Cases
        FNbCasesOccupees: integer;
        FNbCasesTotales: integer;

        // Temperature max (sert pour déterminer la production des satellites solaire et de deutérium)
        FTemperationMax: integer;

        
        // Ressources sur la planète la dernière fois que l'on a téléchargé
        // une page web la concernant
        FLastRessources    : TOGRessourceAll;
        FLastRessourcesDate: int64;



        //
        // Informations concernant la gestion de l'avacuation
        //
        FEvacuationLocalEnable: boolean;
        FEvacuationCoord: TPlanetLocation;
        FEvacuationOrdre: TOGOrdre;
        FEvacuationSpeed: integer;
        

        (***********************************************************************
                         Informations plus importantes
        ************************************************************************

    A présent il faut gérer les éléments qui sont sur la planète...
    C'est très facile de stocker un tableau de GID avec leur niveau
    Idem pour les ressources. Le problème est de permettre une intéraction
    avec le jeu. Par exemple savoir quel élément est en cours de construction ET
    connaitre le lien pour lancer une construction.
    Par la même occasion, nous stockons aussi les ressources nécessaires, le temps
    de construction, etc.
        *)
        
        property cElements     : TListElements   read FListElements;

        property cRessources   : TListRessources read FListRessources;


        (***********************************************************************
                         Construction automatique
        ***********************************************************************)





        property ActionDateFinBatiment       : int64 read FActionDateFinBatiment        write FActionDateFinBatiment;
        property ActionDateFinChantierSpatial: int64 read FActionDateFinChantierSpatial write FActionDateFinChantierSpatial;
        property ActionDateCanRetry          : int64 read FActionDateCanReTry           write FActionDateCanReTry;

        property ActionDateDernierCalculRessource: int64 read FActionDateDernierCalculRessource write FActionDateDernierCalculRessource;


        property HaveNOTBeenUpdated: boolean read FHaveNOTBeenUpdated write FHaveNOTBeenUpdated;





        property pRessourcesProd     : TOGRessourceAll read GetRessourceProd;
        property pEstimatedRessources: TOGRessourceAll read GetEstimatedRessources;
        

        property pLocationStr: string       read GetLocationStr;



        //property cRessourcesToSet: TListRessources read FListRessourcesToSet;

        property cActions    : TCollectionElementActionItem read FActionsList;


        property pShouldUpdateAppercu: boolean read GetShouldUpdateAppercu write SetShouldUpdateAppercu;

        {$IFDEF DEBUG}
           property DebugProc : TsfcProcStatus read FDebugProc write SetDebugProc;
        {$ENDIF}
        
        procedure EvaluationDisponibiliteConstruction;

        function CantBuildThisGIDMustWaitCarConstructEnCours(Gid: integer): boolean;



        

        (***********************************************************************
                         Sauvegarde / Chargement
        ***********************************************************************)
        function SaveToFile(var F: TextFile): boolean;
        function LoadFromFile(var F: TextFile; Section: string): integer;

        // Retourne un tampon à sauvegarder
        function SaveToXML: string;


        (***********************************************************************
                         Constructeur et Destructeur
        ***********************************************************************)
        constructor Create; virtual;
        destructor Destroy; override;


        (***********************************************************************
                         Debogage
        ***********************************************************************)
        procedure DebugTOGRessourceAll(Element: TOGRessourceAll);
        procedure SendDebugAllPlanetInfo;
    end;


    TListPlanet = class(TList)
    private

        function GetProductionTotale: TOGRessourceAll;
        function GetEstimatedRessourcesTotale: TOGRessourceAll;
        function GetRessourcesTotale: TOGRessourceAll;


    public
        // La recherche est commune à toute les planètes, donc gérée
        // au sein de cette classe
        ActionDateFinRecherche: int64;


        property ProductionTotale     : TOGRessourceAll read GetProductionTotale;
        property RessourcesEstimTotale: TOGRessourceAll read GetEstimatedRessourcesTotale;
        property RessourcesTotale     : TOGRessourceAll read GetRessourcesTotale;


        function GetPlanete(Location: TPlanetLocation): TPlaneteInfo;

        function GetPlaneteLaPlusProchePourEvacuation(Location: TPlanetLocation): TPlaneteInfo;


        // Met HaveNOTBeenUpdated de chaque planète à true
        procedure PrepareUpdate;

        // Supprime les planètes qui ont le flag HaveNOTBeenUpdated à true
        function FinalizeUpdate: integer;


        procedure Clear; override;
        destructor Destroy; override;

        constructor Create;
    end;


implementation

uses modBaseRessources;

(*******************************************************************************
    Liste de planètes
*******************************************************************************)

constructor TListPlanet.Create;
begin
    inherited Create;

    ActionDateFinRecherche := 0;
end;

function TListPlanet.GetRessourcesTotale: TOGRessourceAll;
var i: integer;
    p: TPlaneteInfo;
begin
    Result.Metal := -1;

    if Count = 0 then exit;

    p := Items[0];
    Result := p.FLastRessources;
    if Count = 1 then exit;

    for i := 1 to Count - 1 do begin
       p := Items[i];
       Result := mbrAdditionneRessource(Result, p.FLastRessources);
    end;

end;

function TListPlanet.GetEstimatedRessourcesTotale: TOGRessourceAll;
var i: integer;
    p: TPlaneteInfo;
begin
    Result.Metal := -1;

    if Count = 0 then exit;

    p := Items[0];
    Result := p.pEstimatedRessources;
    if Count = 1 then exit;

    for i := 1 to Count - 1 do begin
       p := Items[i];
       Result := mbrAdditionneRessource(Result, p.pEstimatedRessources);
    end;

    
end;

function TListPlanet.GetProductionTotale: TOGRessourceAll;
var i: integer;
    p: TPlaneteInfo;
begin
    Result.Metal := -1;

    if Count = 0 then exit;


    p := Items[0];
    Result := p.pRessourcesProd;
    if Count = 1 then exit;


    for i := 1 to Count - 1 do begin
       p := Items[i];

       Result := mbrAdditionneRessource(Result, p.pRessourcesProd);
    end;

end;

function TListPlanet.FinalizeUpdate: integer;
var i: integer;
    p: TPlaneteInfo;
begin

    Result := 0;

    if Count > 0 then begin

       for i := Count - 1 downto 0 do begin
          p := Items[i];

          if (p <> nil) and (p.HaveNOTBeenUpdated) then begin
             p.Free;
             Items[i] := nil;
             Delete(i);
             
             Inc(Result);
          end;

       end;

    end;

end;



procedure TListPlanet.PrepareUpdate;
var i: integer;
    p: TPlaneteInfo;
begin


    if Count > 0 then begin

       for i := 0 to Count - 1 do begin
          p := Items[i];

          if p <> nil then begin
             p.HaveNOTBeenUpdated := true;
          end;

       end;
    end;

end;

destructor TListPlanet.Destroy;
begin
    Clear;

    inherited Destroy;
end;

procedure TListPlanet.Clear;
var i: integer;
    p: TPlaneteInfo;
begin
    ActionDateFinRecherche := 0;

    if Count > 0 then begin

       for i := 0 to Count - 1 do begin
          p := Items[i];

          if p <> nil then begin
             p.Free;
             Items[i] := nil;
          end;

       end;

    end;

    inherited Clear;
end;


(*******************************************************************************
    Une planète
*******************************************************************************)



function TPlaneteInfo.GetLocationStr: string;
begin
    Result := mbtPlanetLocationToStr(FLocation);
end;


function TPlaneteInfo.GetRessourceProd: TOGRessourceAll;
begin
    //Result := GetCalculTotalParHeure(FListRessources);
    Result := FListRessources.GetProdParHeure;

end;


function TPlaneteInfo.CantBuildThisGIDMustWaitCarConstructEnCours(Gid: integer): boolean;
var CurrDate: int64;
    itype: integer;
begin

    Result := false;
    CurrDate := DateTimeToUnix(Now);
    itype := GetTypeOfGID(Gid);

    if itype = CNT_ITEM_DESIGN_BATIMENT then begin
       if (FActionDateFinBatiment > 100) and (CurrDate < FActionDateFinBatiment) then
          // On n'a pas encore atteint la date de fin
          Result := true;

    end else if (itype = CNT_ITEM_DESIGN_VAISSEAUX) or (itype = CNT_ITEM_DESIGN_DEFENSE) then begin
       // Chantier spatial
       if (FActionDateFinChantierSpatial > 100) and (CurrDate < FActionDateFinChantierSpatial) then
          // On n'a pas encore atteint la date de fin
          Result := true;

    end else begin
       // Sinon recherche probablement ?
       // Pas besoin d'attendre
       // Déjà à false
    end;

    if Result = false then begin
       if (FActionDateCanReTry > 100) and (CurrDate < FActionDateCanReTry) then
          // Pour éviter le flood
          Result := true;

    end;


end;


function TPlaneteInfo.GetEstimatedRessources: TOGRessourceAll;
var ProdHeure: TOGRessourceAll;
    NbSec: integer;
    CurrDate, Diff: int64;
begin

    Result.Metal := -1;

    if FLastRessourcesDate <= 100 then exit;

    CurrDate := DateTimeToUnix(Now);

    if FLastRessourcesDate >= CurrDate then begin
       Result := FLastRessources;
       exit;
    end;

    Diff := CurrDate - FLastRessourcesDate;

    ProdHeure := GetRessourceProd;

    Result.Metal     := mbrGetEstimatedProduction(Diff, ProdHeure.Metal);
    Result.Cristal   := mbrGetEstimatedProduction(Diff, ProdHeure.Cristal);
    Result.Deuterium := mbrGetEstimatedProduction(Diff, ProdHeure.Deuterium);

    Result.Metal     := Result.Metal + FLastRessources.Metal;
    Result.Cristal   := Result.Cristal + FLastRessources.Cristal;
    Result.Deuterium := Result.Deuterium + FLastRessources.Deuterium;
    Result.Energie   := FLastRessources.Energie;
    
end;


procedure TPlaneteInfo.SetShouldUpdateAppercu(Valeur: boolean);
begin
    if Valeur then
       FDateLastApercuUpdate := 0
    else
       FDateLastApercuUpdate := DateTimeToUnix(Now);
       
end;

function TPlaneteInfo.GetShouldUpdateAppercu: boolean;
var cDate: int64;
begin

   if FDateLastApercuUpdate < 500 then begin
      Result := true;
      exit;
   end;

   cDate := DatetimeToUnix(Now);

   Result := false;

   if cDate - FDateLastApercuUpdate > 43200 then begin
      // 172800 = 2 jours
      // 43200  = 12 heures
      Result := true;

   end;


end;



procedure TPlaneteInfo.EvaluationDisponibiliteConstruction;
var WorkingProd: TList;
    CurrentProd: TOGRessourceAll;
begin

    if FLastRessources.Metal     < 0 then exit;
    if FLastRessources.Cristal   < 0 then exit;
    if FLastRessources.Deuterium < 0 then exit;

    if FListRessources.Count = 0 then exit;
    if FListElements.Count   = 0 then exit;

    // ATTENTION/RAPPEL:
    // Les ressources doivent avoir été extraite avec 100% d'activité partout
    // pour pouvoir effectuer l'optimisation
    // UPDATE: On vérifie si il est à 100%, sinon on fait une estimation de la valeur à 100%

    WorkingProd := TList.Create;

    //DupliqueTList(FListRessources, WorkingProd);
    FListRessources.DupliqueTo(WorkingProd);

    CurrentProd := FListRessources.GetProdParHeure;

    // Supprime le facteur de production
    GetRessourceWithoutFactorProduct(WorkingProd);
    
    // Met tout à 100%
    GetRessourceWithBestEstimationOfActivity100(WorkingProd);

    // Calcul le temps de disponibilité
    CalculQuandOnPourraConstruire(FListElements, WorkingProd, CurrentProd, FLastRessources);

    FreeTList(WorkingProd);
    WorkingProd.Free;

end;

procedure TPlaneteInfo.DebugTOGRessourceAll(Element: TOGRessourceAll);
begin
   {$IFDEF DEBUG}
      DoDebug(format('    Metal: %5d', [Element.Metal]));
      DoDebug(format('  Cristal: %5d', [Element.Cristal]));
      DoDebug(format('Deuterium: %5d', [Element.Deuterium]));
      DoDebug(format('  Energie: %5d', [Element.Energie]));
   {$ENDIF}

end;



{$IFDEF DEBUG}
   procedure TPlaneteInfo.SetDebugProc(Element: TsfcProcStatus);
   begin
       FDebugProc := Element;

       FListRessources.DebugProc := FDebugProc;
       FListElements.DebugProc   := FDebugProc;
       FActionsList.DebugProc    := FDebugProc;
   end;

   procedure TPlaneteInfo.DoDebug(const Msg: string);
   begin
       if Assigned(FDebugProc) then
          FDebugProc(Msg);

   end;
{$ENDIF}

procedure TPlaneteInfo.SendDebugAllPlanetInfo;
var i: integer;
    Duree: int64;
begin

{$IFDEF DEBUG}

     DoDebug('------------');
     DoDebug('Planète: ' + mbtPlanetLocationToStr(FLocation));
     DoDebug('');
     DoDebug('Nom: ' + FNom);

     if FIsPlanetMere then
        DoDebug('Planète mère: oui')
     else
        DoDebug('Planète mère: non');

     DoDebug(format('Occupation: %d sur %d cases', [FNbCasesOccupees, FNbCasesTotales]));

     DebugTOGRessourceAll(FLastRessources);


     if FLastRessourcesDate < 100 then begin
        DoDebug('Mise à jour: Inconnu');
     end else begin
        Duree := DateTimeToUnix(Now);

        if Duree < FLastRessourcesDate then begin
           DoDebug('Mise à jour: Invalide');
        end else begin
           Duree := Duree - FLastRessourcesDate;
           DoDebug('Mise à jour: ' + ESBDGetDureeStrings(Duree, true));
        end;
     end;

     // Saut de ligne
     DoDebug('');


     DoDebug('Elements:');
     FListElements.SendToDebugAllInfo;

     DoDebug('Ressources:');
     FListRessources.SendToDebugAllInfo;

     DoDebug('Action Script:');
     FActionsList.SendToDebugAllInfo;

{$ENDIF}

end;

function TListPlanet.GetPlaneteLaPlusProchePourEvacuation(Location: TPlanetLocation): TPlaneteInfo;
var i: integer;
    BestDistance, x: integer;
    cElement: TPlaneteInfo;
begin

    Result := nil;
    if Count = 0 then begin
       exit;
    end;


    BestDistance := maxint;

    for i := 0 to Count - 1 do begin

        cElement := Items[i];

        if CompareLocation(cElement.FLocation, Location) then begin
           // planète identique, on l'ignore
           Continue;
        end;

        if cElement.FLocation.Galaxie <> Location.Galaxie then begin
           // pas dans la même galaxie, cout de deutérium trop élevé
           Continue;
        end;

        // sinon, on a trouvé une planète
        x := cElement.FLocation.SystemSolaire - Location.SystemSolaire;
        if x < 0 then begin
           x := x * -1;
        end;
        if x < BestDistance then begin
           Result := cElement;
           BestDistance := x;
        end;

    end;



    
end;

function TListPlanet.GetPlanete(Location: TPlanetLocation): TPlaneteInfo;
var i: integer;
begin

    if Count = 0 then begin
       Result := nil;
       exit;
    end;

    for i := 0 to Count - 1 do begin

        Result := Items[i];

        if CompareLocation(Result.FLocation, Location) then begin
           // planète trouvée
           exit;
        end;

    end;

    Result := nil;

end;

constructor TPlaneteInfo.Create;
begin
    inherited Create;

    // Listes des ressources
    FListRessources := TListRessources.Create;
    //FListRessourcesToSet := TListRessources.Create;

    // Listes des éléments
    FListElements   := TListElements.Create;

    FActionsList := TCollectionElementActionItem.Create;

        // Position
        FLocation.Galaxie   := -1;
        FLocation.SystemSolaire := -1;
        FLocation.Position  := -1;
        FDateLastApercuUpdate := 0;


        FIsPlanetMere := false;

        FLastRessources.Metal     := 0;
        FLastRessources.Cristal   := 0;
        FLastRessources.Deuterium := 0;
        FLastRessources.Energie   := 0;

        FLastRessourcesDate := 0;

        // Nom
        FNom := '';

        FNbCasesOccupees := -1;
        FNbCasesTotales := -1;

        {$IFDEF DEBUG}
           FDebugProc := nil;
        {$ENDIF}

        FActionDateFinBatiment := 0;
        FActionDateFinChantierSpatial := 0;
        FActionDateCanReTry := 0;

end;


destructor TPlaneteInfo.Destroy;
begin

    FActionsList.Free;
    //FListRessourcesToSet.Free;
    FListRessources.Free;
    FListElements.Free;
    
    inherited Destroy;
end;


const
   // ne pas utiliser de G ni de R et ni de S en début de nom
   CNT_SAVE_NOM_PLANET = 'nom';
   CNT_SAVE_CASES_OCCUPEES = 'casesoccupee';
   CNT_SAVE_CASES_TOTALES = 'casestotales';
   CNT_SAVE_ISMERE = 'mere';
   CNT_SAVE_DateLastAppercuUpdate = 'lastupapp';

   CNT_SAVE_CURR_METAL     = 'cMetal';
   CNT_SAVE_CURR_CRISTAL   = 'cCristal';
   CNT_SAVE_CURR_DEUT      = 'cDeuterium';
   CNT_SAVE_CURR_ENERGIE   = 'cEnergie';
   CNT_SAVE_CURR_RESDATEUP = 'cDate';

   CNT_SAVE_CURR_ActionDateFinBatiment        = 'aFinBat';
   CNT_SAVE_CURR_ActionDateFinChantierSpatial = 'aFinChantier';




procedure TPlaneteInfo.LoadLigne(Ligne: string);
var xPos: integer;
    key: string;
begin

   xPos := pos('=', Ligne);

   if xPos = 0 then exit;

   key := copy(Ligne, 1, xPos - 1);
   System.Delete(Ligne, 1, xPos);

   if SameText(key, CNT_SAVE_NOM_PLANET) then begin
      FNom := Ligne;



   end else if SameText(key, CNT_SAVE_CURR_ActionDateFinBatiment) then begin
      FActionDateFinBatiment         := StrToIntDef(Ligne, 0);
   end else if SameText(key, CNT_SAVE_CURR_ActionDateFinChantierSpatial) then begin
      FActionDateFinChantierSpatial  := StrToIntDef(Ligne, 0);


   end else if SameText(key, CNT_SAVE_CURR_METAL) then begin
      FLastRessources.Metal  := StrToIntDef(Ligne, 0);
   end else if SameText(key, CNT_SAVE_CURR_CRISTAL) then begin
      FLastRessources.Cristal  := StrToIntDef(Ligne, 0);
   end else if SameText(key, CNT_SAVE_CURR_DEUT) then begin
      FLastRessources.Deuterium  := StrToIntDef(Ligne, 0);
   end else if SameText(key, CNT_SAVE_CURR_ENERGIE) then begin
      FLastRessources.Energie  := StrToIntDef(Ligne, 0);
   end else if SameText(key, CNT_SAVE_CURR_RESDATEUP) then begin
      FLastRessourcesDate  := StrToIntDef(Ligne, 0);

   end else if SameText(Key, CNT_SAVE_DateLastAppercuUpdate) then begin
      FDateLastApercuUpdate := StrToIntDef(Ligne, 0);

   end else if SameText(key, CNT_SAVE_CASES_OCCUPEES) then begin
      FNbCasesOccupees := StrToIntDef(Ligne, -1);

   end else if SameText(key, CNT_SAVE_CASES_TOTALES) then begin
      FNbCasesTotales := StrToIntDef(Ligne, -1);

   end else if SameText(key, CNT_SAVE_ISMERE) then begin
      if Ligne = '0' then
         FIsPlanetMere := false
      else
         FIsPlanetMere := true;

   end;


end;


function TPlaneteInfo.LoadFromFile(var F: TextFile; Section: string): integer;
var i: integer;
    s: string;
begin

    Result := -1;
    if Section = '' then exit;

    if Section[1] = '[' then begin
       // Supprime les crochets
       System.Delete(Section, 1, 1);

       i := pos(']', Section);
       if i > 0 then
          System.Delete(Section, i, maxint);

    end;

    // Vérifie si cela correspond à des coordonnées de planète
    i := pos(':', Section);
    if i <= 0 then exit;

    FLocation := mpcExtractPlanetLocation(Section);

    if FLocation.Galaxie < 0       then exit;
    if FLocation.SystemSolaire < 0 then exit;
    if FLocation.Position  < 0     then exit;

    // Ok, sinon cela semble bon

    while NoT(EoF(F)) do begin
       ReadLn(F, s);

       s := trim(s);
       if s = '' then Continue;
       if s[1] = '#' then Continue;
       if s[1] = '/' then Continue;

       if s[1] = 'r' then begin
          FListRessources.LoadFromFile(F, -1);

       end else if s[1] = 'g' then begin
          FListElements.LoadFromFile(F, -1);

       end else if s[1] = 's' then begin
          // Il y obligatoirement un "s" car mêem si il n'y a aucune action
          // le nombre d'action est écrit (donc 0)
          FActionsList.LoadFromFile(F);

          // Après les actions, il n'y a plus rien
          // On sort
          break;

       end else begin
          LoadLigne(s);
       end;

    end;

    Result := 1;

end;

(*
  <planete>
     <nom>Planète X</nom>
     <cases occupees="15" totales="150" />
     <ressources metal="17" cristal="18" deuterium="19" />
  </panete>
*)
const


   CNT_XML_PLANETE_BLOCK = 'planete';

   CNT_XML_PLANETE_CASES = 'cases';
   CNT_XML_PLANETE_CASES_OCCUPEES = 'occupees';
   CNT_XML_PLANETE_CASES_TOTALES  = 'totales';
   CNT_XML_PLANETE_CASES_FORMAT = '<' + CNT_XML_PLANETE_CASES + ' ' + CNT_XML_PLANETE_CASES_OCCUPEES + '="%d" ' + CNT_XML_PLANETE_CASES_TOTALES + '="%d" />';

   CNT_XML_PLANETE_NOM        = 'nom';
   CNT_XML_PLANETE_RESSOURCES = 'ressources';


function TPlaneteInfo.SaveToXML: string;
begin
    Result := '';

    Result := Result + format(CNT_XML_BALISE_OPEN , [CNT_XML_PLANETE_BLOCK]);

      Result := Result + format(CNT_XML_BALISE_OPEN , [CNT_XML_PLANETE_NOM]);
      Result := Result + FNom;
      Result := Result + format(CNT_XML_BALISE_CLOSE, [CNT_XML_PLANETE_NOM]);

      Result := Result + format(CNT_XML_PLANETE_CASES_FORMAT , [FNbCasesOccupees, FNbCasesTotales]);

      Result := Result + format(CNT_XML_RESSOURCES_FORMAT , [FLastRessources.Metal, FLastRessources.Cristal, FLastRessources.Deuterium]);



    Result := Result + format(CNT_XML_BALISE_CLOSE, [CNT_XML_PLANETE_BLOCK]);


end;

function TPlaneteInfo.SaveToFile(var F: TextFile): boolean;
var i: integer;
begin

    // Ecrit le nom de la section
    WriteLn(F, format('[%s]', [mbtPlanetLocationToStr(FLocation)]));
    WriteLn(F, '');

    i := iif(FIsPlanetMere, 1, 0);

    WriteLn(F, '// Général');
    WriteLn(F, format('%s=%s', [CNT_SAVE_NOM_PLANET, FNom]));
    WriteLn(F, format('%s=%d', [CNT_SAVE_CASES_OCCUPEES, FNbCasesOccupees]));
    WriteLn(F, format('%s=%d', [CNT_SAVE_CASES_TOTALES, FNbCasesTotales]));
    WriteLn(F, format('%s=%d', [CNT_SAVE_ISMERE, i]));
    WriteLn(F, format('%s=%d', [CNT_SAVE_DateLastAppercuUpdate, FDateLastApercuUpdate]));

    WriteLn(F, format('%s=%d', [CNT_SAVE_CURR_ActionDateFinBatiment, FActionDateFinBatiment]));
    WriteLn(F, format('%s=%d', [CNT_SAVE_CURR_ActionDateFinChantierSpatial, FActionDateFinChantierSpatial]));



    WriteLn(F, format('%s=%d', [CNT_SAVE_CURR_METAL, FLastRessources.Metal]));
    WriteLn(F, format('%s=%d', [CNT_SAVE_CURR_CRISTAL, FLastRessources.Cristal]));
    WriteLn(F, format('%s=%d', [CNT_SAVE_CURR_DEUT, FLastRessources.Deuterium]));
    WriteLn(F, format('%s=%d', [CNT_SAVE_CURR_ENERGIE, FLastRessources.Energie]));
    WriteLn(F, format('%s=%d', [CNT_SAVE_CURR_RESDATEUP, FLastRessourcesDate]));



    WriteLn(F, '');
    WriteLn(F, '// Ressources');
    FListRessources.SaveToFile(F);

    WriteLn(F, '');
    WriteLn(F, '// Eléments');
    FListElements.SaveToFile(F);


    WriteLn(F, '');
    WriteLn(F, '// Actions');
    FActionsList.SaveToFile(F);

    WriteLn(F, '');
    WriteLn(F, '// Fin planète ' + mbtPlanetLocationToStr(FLocation));
    WriteLn(F, '/////////');
    WriteLn(F, '');
    WriteLn(F, '');
    WriteLn(F, '');
    
end;

end.
